#ifndef TB_CORE_LOCK_HPP_
#define TB_CORE_LOCK_HPP_

#include <boost/atomic/atomic.hpp>

#include "base.hpp"
#include "base_export.hpp"

TB_NAMESPACE_BEGIN

class TB_BASE_API SpinMutex {
public:
  SpinMutex();
  ~SpinMutex();

  bool TryLock();
  void Lock();
  void Unlock();

  class ScopedLock {
   public:
    ScopedLock(SpinMutex& m) : mutex_(m) { mutex_.Lock(); }
    ~ScopedLock() { mutex_.Unlock(); }
   private:
    SpinMutex& mutex_;
  };

private:
  TB_DISABLE_COPY_AND_ASSIGN(SpinMutex);
  struct SpinMutexImpl;
  SpinMutexImpl* impl_;
};

class TB_BASE_API SpinRWMutex {
public:
  SpinRWMutex();
  ~SpinRWMutex();

  bool TryLockShared();
  bool TryLockExclusive();
  void LockShared();
  void UnlockShared();
  void LockExclusive();
  void UnlockExclusive(); 

  class ScopedWriteLock {
  public:
    ScopedWriteLock(SpinRWMutex& m) : mutex_(m) { mutex_.LockExclusive(); }
    ~ScopedWriteLock() { mutex_.UnlockExclusive(); }
  private:
    TB_DISABLE_COPY_AND_ASSIGN(ScopedWriteLock);
    SpinRWMutex& mutex_;
  };

  class ScopedReadLock {
  public:
    ScopedReadLock(SpinRWMutex& m) : mutex_(m) { mutex_.LockShared(); }
    ~ScopedReadLock() { mutex_.UnlockShared(); }
  private:
    TB_DISABLE_COPY_AND_ASSIGN(ScopedReadLock);
    SpinRWMutex& mutex_;
  };

private:
  TB_DISABLE_COPY_AND_ASSIGN(SpinRWMutex);
  struct SpinRWMutexImpl;
  SpinRWMutexImpl* impl_;
};

TB_NAMESPACE_END

#endif  //TB_CORE_LOCK_HPP_
